using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Prism.Commands;
using Prism.Events;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using WPFNote.Models;
using WPFNote.Models.Dto;
using WPFNote.Services.IDal;
using WPFNote.Utilities;
using WPFNote.Utilities.Common;
using WPFNote.Utilities.Extensions;

namespace WPFNote.ViewModels
{
    public class MainWindowViewModel : BindableBase, IConfigureService
    {
        private readonly IRegionManager _regionManager;
        private readonly IDialogHostService _dialogHost;
        private IRegionNavigationJournal _journal;
        private readonly IEventAggregator _aggregator;
        private readonly ICategory _category;
        private readonly INote _note;
        private readonly IContainerProvider _containerProvider;
        private int _categoryId = 0;
        public DelegateCommand<Category> NavigateCommand { get; }
        public DelegateCommand IndexCommand { get; }
        public DelegateCommand RefreshCommand { get; }
        public DelegateCommand SaveCategoryCommand { get; }
        public DelegateCommand AddCategoryCommand { get; }
        public DelegateCommand<Category> EditCategoryCommand { get; }
        public DelegateCommand<Category> DeleteCategoryCommand { get; }
        public DelegateCommand LogoutCommand { get; }
        public DelegateCommand ConfigCommand { get; }
        public DelegateCommand UploadCommand { get; }
        public DelegateCommand DownloadCommand { get; }

        private Models.Users _userInfo;

        public Models.Users UserInfo
        {
            get { return _userInfo; }
            set
            {
                _userInfo = value;
                RaisePropertyChanged();
            }
        }

        private List<Models.Category> _categories;

        public List<Models.Category> Categories
        {
            get { return _categories; }
            set
            {
                _categories = value;
                RaisePropertyChanged();
            }
        }

        private bool _isRightDrawerOpen;

        /// <summary>
        /// 右侧编辑窗口是否展开
        /// </summary>
        public bool IsRightDrawerOpen
        {
            get { return _isRightDrawerOpen; }
            set
            {
                _isRightDrawerOpen = value;
                RaisePropertyChanged();
            }
        }

        private string _categoryDtoType;

        public string CategoryDtoType
        {
            get => _categoryDtoType;
            set
            {
                _categoryDtoType = value;
                RaisePropertyChanged();
            }
        }

        private string _categoryTitle;

        public string CategoryTitle
        {
            get => _categoryTitle;
            set
            {
                _categoryTitle = value;
                RaisePropertyChanged();
            }
        }

        private string _categorySort;

        public string CategorySort
        {
            get => _categorySort;
            set
            {
                _categorySort = value;
                RaisePropertyChanged();
            }
        }

        private CategoryDtoInput _categoryDto;

        public CategoryDtoInput CategoryDto
        {
            get => _categoryDto;
            set
            {
                _categoryDto = value;
                RaisePropertyChanged();
            }
        }

        public MainWindowViewModel(IContainerProvider containerProvider, IEventAggregator aggregator,
            IRegionManager regionManager, ICategory category, INote note,
            IRegionNavigationJournal journal)
        {
            _containerProvider = containerProvider;
            _regionManager = regionManager;
            _aggregator = aggregator;
            _category = category;
            _note = note;
            _journal = journal;
            _dialogHost = containerProvider.Resolve<IDialogHostService>();
            NavigateCommand = new DelegateCommand<Category>(Navigate);
            IndexCommand = new DelegateCommand(() => { LoadIndex(); });
            RefreshCommand = new DelegateCommand(async () => { await LoadCategories(); });
            AddCategoryCommand = new DelegateCommand(AddCategory);
            SaveCategoryCommand = new DelegateCommand(SaveCategory);
            EditCategoryCommand = new DelegateCommand<Category>(EditCategory);
            DeleteCategoryCommand = new DelegateCommand<Category>(DeleteCategory);
            LogoutCommand = new DelegateCommand(Logout);
            ConfigCommand = new DelegateCommand(OpenToConfig);
            UploadCommand = new DelegateCommand(ExecUploadCmd);
            DownloadCommand = new DelegateCommand(ExecDownloadCmd);
            // 启动时，判断数据表是否已经存在，不存在则创建
            category.CreateTable();
        }

        private void AddCategory()
        {
            CategoryDto = new CategoryDtoInput();
            CategoryTitle = "";
            CategorySort = "";
            IsRightDrawerOpen = true;
            CategoryDtoType = "添加分类";
        }

        private async void SaveCategory()
        {
            if (string.IsNullOrWhiteSpace(CategoryTitle))
            {
                _aggregator.SendMessage("请填写分类名称");
                return;
            }

            if (string.IsNullOrWhiteSpace(CategorySort))
            {
                _aggregator.SendMessage("请填写分类排序");
                return;
            }

            if (new Regex("[^0-9.-]+").IsMatch(CategorySort))
            {
                _aggregator.SendMessage("分类排序只能是整数");
                return;
            }

            CategoryDto.Title = CategoryTitle;
            CategoryDto.Sort = int.Parse(CategorySort);
            var result = CategoryDtoType == "添加分类"
                ? await _category.InsertAsync(new Category()
                {
                    Title = CategoryDto.Title,
                    Sort = CategoryDto.Sort ?? 1,
                    TypeId = CategoryDto.TypeId,
                    UserId = AppSession.UserInfo.Id
                })
                : await _category.UpdateAsync(new Category()
                {
                    Id = CategoryDto.Id,
                    Title = CategoryDto.Title,
                    Sort = CategoryDto.Sort ?? 1,
                    TypeId = CategoryDto.TypeId,
                    UserId = AppSession.UserInfo.Id
                });
            if (result)
            {
                _aggregator.SendMessage("保存成功");
                await LoadCategories();
                IsRightDrawerOpen = false;
            }
            else
            {
                _aggregator.SendMessage("保存失败");
            }
        }

        private async void EditCategory(Category model)
        {
            if (model == null || model.Id <= 0)
                return;
            var result = await _category.SelectAsync(model.Id);
            if (result == null)
            {
                _aggregator.SendMessage("获取笔记分类失败");
                return;
            }

            if (result != null)
            {
                CategoryDto = new CategoryDtoInput()
                {
                    Id = result.Id,
                    Title = result.Title,
                    Sort = result.Sort,
                    TypeId = result.TypeId
                };
                CategoryTitle = CategoryDto.Title;
                CategorySort = CategoryDto.Sort.ToString();
                IsRightDrawerOpen = true;
                CategoryDtoType = "编辑分类";
            }
        }

        private async void DeleteCategory(Category model)
        {
            var dialogResult = await _dialogHost.Question("温馨提示", $"确认删除分类:{model.Title} ?");
            if (dialogResult.Result != Prism.Services.Dialogs.ButtonResult.OK)
                return;
            var noteList = await _note.SelectListAsync(new NoteSch() { CategoryId = model.Id });
            if (noteList != null && noteList.Count > 0)
            {
                _aggregator.SendMessage("该分类下还存在笔记， 不可删除");
                return;
            }

            var result = await _category.DeleteAsync(model.Id);
            if (result)
            {
                _aggregator.SendMessage("删除成功");
                CategoryDto = new CategoryDtoInput();
                IsRightDrawerOpen = false;
                await LoadCategories();
            }
            else
            {
                _aggregator.SendMessage("删除失败");
            }
        }

        private async void Logout()
        {
            if (File.Exists(AppSession.UserInfoPath))
            {
                File.Delete(AppSession.UserInfoPath);
            }

            await UploadDataBase();
            Application.Current.Shutdown();
        }

        /// <summary>
        /// 加载分类列表
        /// </summary>
        private async Task LoadCategories()
        {
            var result = await _category.SelectListAsync(new CategorySch());
            if (result is { Count: > 0 })
            {
                Categories = result;
            }
        }

        private void Navigate(Category model)
        {
            if (model is not { Id: > 0 })
                return;
            _categoryId = model.Id;
            LoadIndex();
        }

        private void OpenToConfig()
        {
            var dialog = _containerProvider.Resolve<IDialogService>();
            dialog.ShowDialog("Config");
        }

        private async void ExecUploadCmd()
        {
            var dialogResult = await _dialogHost.Question("温馨提示", "确认上传笔记数据到云端 ?");
            if (dialogResult.Result != ButtonResult.OK)
            {
                return;
            }

            await UploadDataBase(true);
        }

        private async void ExecDownloadCmd()
        {
            var dialogResult = await _dialogHost.Question("温馨提示", "确认从云端下载笔记 ? 此操作会覆盖本地数据 !");
            if (dialogResult.Result != ButtonResult.OK)
            {
                return;
            }
            await DownloadDataBase(true);
        }

        public async Task UploadDataBase(bool isManual = false)
        {
            if (!Config.Init().BooleanParam.IsAsync && !isManual)
            {
                return;
            }

            _aggregator.SendMessage("请稍后，正在上传笔记数据...");
            // 备份最新数据库文件
            var error = new DataBaseHelper().BackUp(out var dbZipFile);
            if (!string.IsNullOrWhiteSpace(error))
            {
                _aggregator.SendMessage(error);
                return;
            }

            // 上传数据库文件包到云端
            var url = await new Utilities.Cloud.TencentCloud().UploadFile(AppSession.UserInfo.UserName, dbZipFile);
            if (string.IsNullOrWhiteSpace(url))
            {
                const string failedMsg = "笔记数据上传失败";
                NotificationHelper.Toast("通知", failedMsg);
                _aggregator.SendMessage(failedMsg);
                return;
            }

            const string successMsg = "笔记数据上传成功";
            _aggregator.SendMessage(successMsg);
            NotificationHelper.Toast("通知", successMsg);
            Thread.Sleep(1500);
        }

        private async Task DownloadDataBase(bool isManual = false)
        {
            if (!Config.Init().BooleanParam.IsAsync && !isManual)
            {
                return;
            }
            _aggregator.SendMessage("请稍后，正在下载笔记数据...");

            var databaseFolder = AppSession.DbBackUpPath;
            if (!Directory.Exists(databaseFolder))
            {
                Directory.CreateDirectory(databaseFolder);
            }

            var filePath = Path.Combine(AppSession.DbBackUpPath, "cloud.zip");
            var ok = await new Utilities.Cloud.TencentCloud().DownloadFile(AppSession.UserInfo.UserName, filePath);
            if (!ok)
            {
                return;
            }

            ok = new DataBaseHelper().Import(filePath);
            if (!ok)
            {
                return;
            }

            _aggregator.SendMessage("笔记数据下载成功");
            await Load();
        }

        /// <summary>
        /// 配置首页初始化参数
        /// </summary>
        public async void Configure()
        {
            UserInfo = AppSession.UserInfo;
            // await DownloadDataBase();
            await Load();
        }

        private async Task Load()
        {
            await LoadCategories();
            LoadIndex();
        }

        private void LoadIndex()
        {
            _regionManager.RequestNavigate(PrismManager.MainViewRegionName, "Index", new NavigationParameters()
            {
                {
                    "id", _categoryId
                }
            });
        }
    }
}